﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Joy.Erp.BasicArchives.Customers;
using Joy.Erp.Ufida.Core;
using Microsoft.Extensions.Logging;

namespace Joy.Erp.Ufida.Customers
{
    public class CustomerTypeSyncAppService : UfidaAppService, ICustomerTypeSyncAppService
    {
        protected ICustomerTypeRepository CustomerTypeRepository => LazyServiceProvider.LazyGetRequiredService<ICustomerTypeRepository>();
        protected ICustomerTypeAppService CustomerTypeAppService => LazyServiceProvider.LazyGetRequiredService<ICustomerTypeAppService>();
        protected ICustomerCategoryUfidaAppService CustomerCategoryUfidaAppService => LazyServiceProvider.LazyGetRequiredService<ICustomerCategoryUfidaAppService>();
        protected CustomerTypeManager CustomerTypeManager => LazyServiceProvider.LazyGetRequiredService<CustomerTypeManager>();

        public async Task<AnalysisDto> AnalyzeAsync()
        {
            var analysisDto = new AnalysisDto();
            analysisDto.Id = typeof(CustomerType).FullName;

            var u9list = await CustomerCategoryUfidaAppService.GetAllAsync();
            var u9Ids = u9list.Select(x => x.ID.ToString()).ToHashSet();
            analysisDto.U9Count = u9Ids.Count;

            var pmcQuery = await CustomerTypeRepository.GetQueryableAsync();
            analysisDto.Count = await AsyncExecuter.CountAsync(pmcQuery.Where(x => !x.IsDeleted));

            var syncedSourceKeys = await AsyncExecuter.ToListAsync(
                pmcQuery
                    .Where(x => !x.IsDeleted && x.SourceType == SourceConfig.SourceType)
                    .Select(x => x.SourceKey)
            );

            analysisDto.AsyncCount = syncedSourceKeys.Count(key => u9Ids.Contains(key));
            analysisDto.UnasyncCount = analysisDto.U9Count - analysisDto.AsyncCount;
            analysisDto.SelfCount = analysisDto.Count - analysisDto.AsyncCount;

            return analysisDto;
        }

        public async Task<List<long>> GetUnasyncIds()
        {
            var u9list = await CustomerCategoryUfidaAppService.GetAllAsync();
            var u9Ids = u9list.Select(x => x.ID).ToList();

            var pmcQuery = await CustomerTypeRepository.GetQueryableAsync();
            var syncedSourceKeys = await AsyncExecuter.ToListAsync(
                pmcQuery
                    .Where(x => !x.IsDeleted && x.SourceType == SourceConfig.SourceType)
                    .Select(x => x.SourceKey)
            );

            var syncedSourceKeySet = new HashSet<string>(syncedSourceKeys);

            var unasyncIds = u9Ids
                .Where(id => !syncedSourceKeySet.Contains(id.ToString()))
                .ToList();

            return unasyncIds;
        }

        public async Task<int> CreateByIdsAsync(long[] ids)
        {
            if (ids == null || ids.Length == 0)
                return 0;

            // 批量预查询已存在的记录，避免循环查询数据库
            var pmcQuery = await CustomerTypeRepository.GetQueryableAsync();
            var idStrings = ids.Select(id => id.ToString()).ToList();
            var existingSourceKeys = await AsyncExecuter.ToListAsync(
                pmcQuery
                    .Where(x =>
                        idStrings.Contains(x.SourceKey) && x.SourceType == SourceConfig.SourceType
                    )
                    .Select(x => x.SourceKey)
            );
            var existingSet = new HashSet<string>(existingSourceKeys);

            // 过滤出需要创建的ID
            var needCreateIds = ids.Where(id => !existingSet.Contains(id.ToString())).ToList();
            if (needCreateIds.Count == 0)
                return ids.Length;

            Logger.LogInformation($"[批量同步-客户类型] 开始处理 {needCreateIds.Count} 条新增，已存在 {existingSet.Count} 条");

            // 为了确保父级先于子级创建，需要先获取U9数据并按Code长度排序
            var u9DataList = new List<(long id, CustomerCategoryUfidaDto dto)>();
            foreach (var id in needCreateIds)
            {
                try
                {
                    var customerCategoryUfidaDto = await CustomerCategoryUfidaAppService.GetAsync(id);
                    if (customerCategoryUfidaDto != null)
                    {
                        u9DataList.Add((id, customerCategoryUfidaDto));
                    }
                }
                catch (Exception ex)
                {
                    Logger.LogWarning(ex, $"[批量同步-客户类型] 获取U9数据失败，Id: {id}");
                }
            }

            if (u9DataList.Count == 0) return existingSet.Count;

            // 按Code长度排序，确保父级先于子级创建
            var sortedList = u9DataList.OrderBy(x => x.dto.Code?.Length ?? int.MaxValue).ToList();

            var successCount = 0;
            using (var uow = UnitOfWorkManager.Begin(new Volo.Abp.Uow.AbpUnitOfWorkOptions(), requiresNew: true))
            {
                try
                {
                    foreach (var (id, dto) in sortedList)
                    {
                        try
                        {
                            var result = await CreateByIdAsync(id);
                            if (result)
                            {
                                successCount++;
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.LogWarning(ex, $"[批量同步-客户类型] 创建实体失败，Id: {id}");
                        }
                    }

                    await uow.CompleteAsync();
                }
                catch (Exception ex)
                {
                    Logger.LogWarning(ex, $"[批量同步-客户类型] 批量创建失败，{ex.Message}");
                }
            }

            Logger.LogInformation($"[批量同步-客户类型] 完成！成功新增 {successCount} 条，总计 {successCount + existingSet.Count} 条");

            return successCount + existingSet.Count;
        }

        public async Task<List<long>> GetSyncedIds()
        {
            var pmcQuery = await CustomerTypeRepository.GetQueryableAsync();
            var syncedSourceKeys = await AsyncExecuter.ToListAsync(
                pmcQuery
                    .Where(x => !x.IsDeleted && x.SourceType == SourceConfig.SourceType)
                    .Select(x => x.SourceKey)
            );

            return syncedSourceKeys
                .Select(key => long.TryParse(key, out var parsedId) ? (long?)parsedId : null)
                .Where(id => id.HasValue)
                .Select(id => id.Value)
                .ToList();
        }

        public async Task<int> UpdateByIdsAsync(long[] ids)
        {
            if (ids == null || ids.Length == 0)
                return 0;

            Logger.LogInformation($"[批量同步-客户类型] 开始处理 {ids.Length} 条客户类型更新");

            var pmcQuery = await CustomerTypeRepository.GetQueryableAsync();
            var idStrings = ids.Select(id => id.ToString()).ToList();
            var existingEntities = await AsyncExecuter.ToListAsync(
                pmcQuery.Where(x =>
                    idStrings.Contains(x.SourceKey) && x.SourceType == SourceConfig.SourceType
                )
            );

            if (existingEntities.Count == 0)
            {
                Logger.LogWarning($"[批量同步-客户类型] 没有找到需要更新的记录");
                return 0;
            }

            var entityDict = existingEntities.ToDictionary(x => x.SourceKey, x => x);
            var needHandleIds = ids.Where(id => entityDict.ContainsKey(id.ToString())).ToList();
            if (needHandleIds.Count == 0)
                return 0;

            var allU9DataDict = await BatchLoadCustomerCategories(needHandleIds);

            var entitiesToUpdate = new List<CustomerType>();
            var entitiesToDelete = new List<CustomerType>();

            foreach (var id in needHandleIds)
            {
                try
                {
                    if (!entityDict.TryGetValue(id.ToString(), out var entity))
                        continue;

                    if (!allU9DataDict.TryGetValue(id, out var u9Data))
                    {
                        entitiesToDelete.Add(entity);
                        continue;
                    }

                    entity.DisplayName = u9Data.Name;
                    //entity.Code = u9Data.Code;   树结构的Code在pmc中不能赋值
                    entity.SourceCreatedOn = u9Data.CreatedOn;

                    entitiesToUpdate.Add(entity);
                }
                catch (Exception ex)
                {
                    Logger.LogWarning(ex, $"[批量同步-客户类型] 处理实体失败，Id: {id}");
                }
            }

            var updateCount = 0;
            var deleteCount = 0;

            using (var uow = UnitOfWorkManager.Begin(new Volo.Abp.Uow.AbpUnitOfWorkOptions(), requiresNew: true))
            {
                try
                {
                    if (entitiesToUpdate.Count > 0)
                    {
                        await CustomerTypeRepository.BulkUpdateAsync(
                            entitiesToUpdate,
                            autoSave: false
                        );
                        updateCount = entitiesToUpdate.Count;
                    }

                    if (entitiesToDelete.Count > 0)
                    {
                        await CustomerTypeRepository.BulkDeleteAsync(
                            entitiesToDelete,
                            autoSave: false
                        );
                        deleteCount = entitiesToDelete.Count;
                    }

                    await uow.CompleteAsync();
                }
                catch (Exception ex)
                {
                    Logger.LogWarning(ex, $"[批量同步-客户类型] 批量更新/删除失败，{ex.Message}");
                }
            }

            Logger.LogInformation($"[批量同步-客户类型] 完成！成功更新 {updateCount} 条，删除 {deleteCount} 条");

            return updateCount + deleteCount;
        }

        private async Task<bool> CreateByIdAsync(long id)
        {
            var existCustomerType = await CustomerTypeAppService.FindBySourceKeyAsync(id.ToString(), SourceConfig.SourceType);
            if (existCustomerType != null) return true;

            var customerCategoryUfidaDto = await CustomerCategoryUfidaAppService.GetAsync(id);
            if (customerCategoryUfidaDto == null) return false;

            try
            {
                await CreateAsync(customerCategoryUfidaDto);
                return true;
            }
            catch (Exception ex)
            {
                Logger.LogWarning(ex, $"CreateByIdAsync 创建失败，Id: {id}, 错误信息：{ex.Message}");
                return false;
            }
        }

        private async Task<CustomerTypeDto> CreateAsync(CustomerCategoryUfidaDto customerCategoryUfidaDto)
        {
            var customerTypeCreateDto = new CustomerTypeCreateDto();
            customerTypeCreateDto.SourceType = SourceConfig.SourceType;
            customerTypeCreateDto.SourceKey = customerCategoryUfidaDto.ID.ToString();
            customerTypeCreateDto.DisplayName = customerCategoryUfidaDto.Name;
            customerTypeCreateDto.SourceCreatedOn = customerCategoryUfidaDto.CreatedOn;
            customerTypeCreateDto.ParentId = null;

            // CustomerType 的父级关系处理：如果 Code 有层级结构，可以通过 Code 长度判断
            // 这里简化处理，如果需要处理父级关系，可以参考 ItemCategory 的实现
            // 由于 CustomerCategoryUfidaDto 没有 TreeRule，暂时不处理父级关系

            return await CustomerTypeAppService.CreateAsync(customerTypeCreateDto);
        }

        private async Task<Dictionary<long, CustomerCategoryUfidaDto>> BatchLoadCustomerCategories(List<long> ids)
        {
            var result = new Dictionary<long, CustomerCategoryUfidaDto>();
            if (ids == null || ids.Count == 0) return result;

            foreach (var id in ids)
            {
                try
                {
                    var dto = await CustomerCategoryUfidaAppService.GetAsync(id);
                    if (dto != null)
                    {
                        result[id] = dto;
                    }
                }
                catch (Exception ex)
                {
                    Logger.LogWarning(ex, $"[批量同步-客户类型] 获取U9数据失败，Id: {id}");
                }
            }

            return result;
        }
    }
}
